package ClientFront;

import ClientFront.Listeners.MsgReciver;
import ClientFront.Net.ConnectionInfo;
import ClientFront.Net.MsgTypeEnum;
import ClientFront.Net.NetMsgDealer;
import Server.BlankTypeEnum;
import Server.ServerConsts;

import javax.swing.*;
import javax.swing.table.TableRowSorter;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;

public class ClientGamePanel extends MyPanel implements MsgReciver{
    NetMsgDealer msgDealer;
    ConnectionInfo cinfo;
    Thread msgth,apprth;
    String userName;
    String otherName;
    ChessBoard board  = new ChessBoard();
    BoardAppr boardAppr= new BoardAppr();

    public ClientGamePanel(){
        msgDealer = new NetMsgDealer();
    }
    public ClientGamePanel(ConnectionInfo c, String userName){
        this.userName = userName;
        setLayout(null);
        add(boardAppr);
        boardAppr.setGamePanel(this);
        msgth = new Thread(msgDealer);
        apprth = new Thread(()->{
            try {
                Thread.sleep(ServerConsts.SLEEP_MILLIS);
                boardAppr.repaint();
            }catch (Exception e){}
        });
        apprth.start();
        startConnection();
    }
    public void initWithOption(String userName){
        this.userName = userName;
        setLayout(null);
        add(boardAppr);
        boardAppr.setGamePanel(this);
        msgth = new Thread(msgDealer);
        apprth = new Thread(()->{
            try {
                while (true){
                    Thread.sleep(ServerConsts.SLEEP_MILLIS);
                    boardAppr.repaint();
                }

            }catch (Exception e){}

        });
        apprth.start();
        startConnection();
    }

    public void setMsgDealer(NetMsgDealer msgDealer) {
        this.msgDealer = msgDealer;
        msgDealer.setMsgReciver(this);
    }


    public void startConnection(){
        msgth.start();
    }
    @Override
    public void sendMsg(NetMsg msg) {
        dealMsg(msg);
    }

    /**
     * 观察者给NetMsgDealer
     * @param Msg
     */
    public void dealMsg(NetMsg Msg){
        System.out.println("收到消息："+Msg.getMsgType().name());
        switch (Msg.msgType){
        case LINKERROR :
            JOptionPane.showMessageDialog(null,Msg.args[0],"提示",JOptionPane.INFORMATION_MESSAGE);
            msgth.interrupt();
            setVisible(false);
            return;
            case USEBLACK:
                board.setPlayingPlayer(BlankTypeEnum.BLACK);
                break;
            case USEWHITE:
                board.setPlayingPlayer(BlankTypeEnum.WHITE);
                break;
            case GAMESTART:
                System.out.println("对局开始！");
                break;
            case YOURTURN:
                board.setMyTurn(true);
                break;
            case STEP:
                int[] step = MyUtils.stepToint(Integer.parseInt(Msg.getArgs()[0]));
                switch (board.playingPlayer) {
                    case BLACK -> board.setChess(BlankTypeEnum.WHITE, step[0], step[1]);
                    case WHITE -> board.setChess(BlankTypeEnum.BLACK, step[0], step[1]);
                }
                break;
            case WIN:
                JOptionPane.showMessageDialog(null,"你赢了！");
                restart();
            case LOSE:
                JOptionPane.showMessageDialog(null,"你输了！");
                restart();

        }
    }
    void restart(){
        board.init();
    }



    protected class ChessBoard
    {
        boolean myTurn;
        BlankTypeEnum[][] board = new BlankTypeEnum[ServerConsts.BOARD_LEN][ServerConsts.BOARD_LEN];
        BlankTypeEnum playingPlayer = BlankTypeEnum.BLANK;
        public ChessBoard(){
            for (int i = 0; i < ServerConsts.BOARD_LEN; i++) {
                for (int j = 0; j < ServerConsts.BOARD_LEN; j++) {
                    board[i][j] = BlankTypeEnum.BLANK;
                }
            }
        }

        public void setPlayingPlayer(BlankTypeEnum playingPlayer) {
            this.playingPlayer = playingPlayer;
        }

        public void setMyTurn(boolean myTurn) {
            this.myTurn = myTurn;
        }

        void setChess(BlankTypeEnum chessType, int x, int y){
            if(!(chessType == BlankTypeEnum.WHITE || chessType == BlankTypeEnum.BLACK)){
                return;
            }
            if(x < 0 || x >= 15 || y < 0 || y >= 15){
                return;
            }
            if(board[x][y] != BlankTypeEnum.BLANK){
                return;
            }
            if(!myTurn && chessType == playingPlayer){
                return;
            }
            if(myTurn && chessType == playingPlayer){
               myTurn =false;
            }

            board[x][y] = chessType;
            System.out.println("一枚棋放在"+x+" "+y);
            if(chessType == playingPlayer){
                msgDealer.sendMsg(new NetMsg(MsgTypeEnum.STEP,""+MyUtils.intToStep(x,y)));
            }

        }

        void init(){
            for (int i = 0; i < ServerConsts.BOARD_LEN; i++) {
                for (int j = 0; j < ServerConsts.BOARD_LEN; j++) {
                    board[i][j] = BlankTypeEnum.BLANK;
                }
            }
        }

        void backStep(int step){
            int[] place = MyUtils.stepToint(step);
            setChess(BlankTypeEnum.BLANK,place[0],place[1]);
        }
        BlankTypeEnum getPointType(int x,int y){
            return board[x][y];
        }
    }
    protected class BoardAppr extends JPanel{

        int mxp,myp;
        int startx = 30;
        int starty = 30;
        int spacing;
        int chessRadius;
        ClientGamePanel gamePanel;

        public BoardAppr(){
            setBounds(0,0,MainWindow.HEIGHT,MainWindow.HEIGHT);
            spacing = (getHeight()-(2*startx))/ ServerConsts.BOARD_LEN-1;
            chessRadius = spacing/2 - 2;
            addMouseMotionListener(new MouseMotionAdapter() {
                @Override
                public void mouseMoved(MouseEvent e) {
                    super.mouseMoved(e);
                    int mx,my;
                    mx = e.getX();
                    my = e.getY();
                    mxp = (mx-startx) / spacing;
                    myp = (my-starty) / spacing;
                }
            });
            addMouseListener(new MouseAdapter() {
                @Override
                public void mouseClicked(MouseEvent e) {
                    super.mouseClicked(e);
                    if(mxp >=0 &&mxp<ServerConsts.BOARD_LEN &&
                        myp >= 0 && myp < ServerConsts.BOARD_LEN){
                            gamePanel.board.setChess(gamePanel.board.playingPlayer,mxp,myp);
                        System.out.println("setChessAt"+mxp+":"+myp);
                    }
                }
            });
        }
        @Override
        public void paint(Graphics g) {
            super.paint(g);
            Color backGroundColor = new Color(255, 190, 120);
            Color lineColor = new Color(40,40,40);
            Color blackChessColor = new Color(50,50,50);
            Color whiteChessColor = new Color(240,240,240);

            g.setColor(backGroundColor);
            g.fillRect(0,0,getWidth(),getHeight());

            g.setColor(lineColor);
            for (int i = 0; i <= ServerConsts.BOARD_LEN; i++) {
                //shuxian
                g.drawLine(startx+(i*spacing), starty,
                        startx+(i*spacing),starty+(getHeight()-2*spacing));
                g.drawLine(startx,starty+(i*spacing),
                        startx+(getWidth()-2*spacing),starty+(i*spacing));
            }
            for (int i = 0; i < ServerConsts.BOARD_LEN; i++) {
                for (int j = 0; j < ServerConsts.BOARD_LEN; j++) {
                    BlankTypeEnum type = board.getPointType(i,j);
                    switch (type){
                        case BLANK : continue;
                        case BLACK:g.setColor(blackChessColor);break;
                        case WHITE:g.setColor(whiteChessColor);break;
                    }
                    g.fillOval(startx+(i*spacing) - chessRadius,starty+(j*spacing)-chessRadius,
                            chessRadius*2,chessRadius*2);
                }
            }
            if(board.playingPlayer == BlankTypeEnum.BLACK){
                g.setColor(blackChessColor);
            }
            if(board.playingPlayer == BlankTypeEnum.WHITE){
                g.setColor(whiteChessColor);
            }
            String mytype = board.playingPlayer == BlankTypeEnum.BLACK?"黑棋":"白棋";
            g.drawString("您执"+mytype,0,30);
            //g.fillOval(850,30,chessRadius*2,chessRadius*2);
            g.setColor(Color.BLACK);
            g.drawRect(startx+(mxp*spacing) - chessRadius,starty+(myp*spacing)-chessRadius,
                    chessRadius*2,chessRadius*2);

        }

        public BoardAppr setGamePanel(ClientGamePanel gamePanel) {
            this.gamePanel = gamePanel;
            return this;
        }
    }

}
